//  --- 捕获异常 ---

/*
在Java中,凡是可能抛出Exception的语句,都可以使用try...catch捕获。

把可能发生Exception的语句放在try {...}中,然后使用catch(Exception) {...}捕获对应的Exception及其子类。

-----------------------------------------------------

# 多catch语句 #

可以使用多个catch语句,每个catch分别捕获对应的Exception及其子类。JVM在捕获到异常后,会从上到下匹配catch语句,匹配到某个catch后,执行catch代码块,然后不再继续匹配。

简单地说就是：多个catch语句只有一个能被执行。例如： */
public static void main(String[] args) {
	try {
		process1();
		process2();
		process3();
	} catch (IOException e) {
		System.out.println(e);
	} catch (NumberFormatException e) {
		System.out.println(e);
	}
}

//存在多个catch的时候,catch的顺序非常重要:子类必须写在前面。例如：
public static void main(String[] args) {
	try {
		process1();
		process2();
		process3();
	} catch (IOException e) {
		System.out.println("IO error");
	} catch (UnsupportedEncodingException e) {
		//永远捕获不到
		System.out.println("Bad encoding");
	}
}

/*
对于上面的代码,UnsupportedEncodingException异常是永远无法捕获到的,因为他是IOException的子类,捕获了IOException e已经包括了UnsupportedEncodingException e。

所以,当抛出UnsupportedEncodingException异常的时候,会被catch(IOException e) {...}捕获并执行。

因此,正确的写法是把子类放到前面:  */
public static void main(String[] args) {
	try {
		process1();
        process2();
        process3();
	} catch (UnsupportedEncodingException e) {
		System.out.println("Bad encoding");
	} catch (IOException e) {
		System.out.println("IO error");
	}
}

/* -----------------------------------------------

#	finally    #

无论是否有异常发生,我们都希望执行一些语句,例如清理工作,怎么写?

可以把执行语句写若干遍：正常执行的放到try中,每个catch再写一遍。例如：  */
public static void main(String[] args) {
	try {
		process1();
        process2();
        process3();
        System.out.println("END");
	} catch (UnsupportedEncodingException e) {
		System.out.println("Bad encoding");
		System.out.println("End");
	} catch (IOException e) {
		System.out.println("IO error");
		System.out.println("End");
	}
}
/*
上述代码无论是否发生异常，都会执行System.out.println("END");这条语句。

那么如何消除这些重复的代码？Java的try ... catch机制还提供了finally语句，finally语句块保证有无错误都会执行。上述代码可以改写如下：  */
public static void main(String[] args) {
	try {
		process1();
        process2();
        process3();
	}  catch (UnsupportedEncodingException e) {
        System.out.println("Bad encoding");
    } catch (IOException e) {
        System.out.println("IO error");
    } finally {
    	System.out.println("End"); //无论是否有Exception,都执行
    }
}
/*
注意finally有几个特点：
	1.finally语句不是必须的，可写可不写；
	2.finally总是最后执行。

如果没有发生异常，就正常执行try { ... }语句块，然后执行finally。如果发生了异常，就中断执行try { ... }语句块，然后跳转执行匹配的catch语句块，最后执行finally。

可见，finally是用来保证一些代码必须执行的。

-------------------------------------------------

某些情况下，可以没有catch，只使用try ... finally结构。例如：  */
public class Main {
	void process(String file) throws IOException {
		try {
			//...
		} finally {
			System.out.println("End");
		}
	}
}
/*因为方法声明了可能抛出的异常，所以可以不写catch。

-----------------------------------------------------

#  捕获多种异常  # 

如果某些异常的处理逻辑相同，但是异常本身不存在继承关系，那么就得编写多条catch子句： */
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException e) {
        System.out.println("Bad input");
    } catch (NumberFormatException e) {
        System.out.println("Bad input");
    } catch (Exception e) {
        System.out.println("Unknown error");
    }
}
//因为处理IOException和NumberFormatException的代码是相同的，所以我们可以把它两用|合并到一起：
public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException | NumberFormatException e) { // IOException 或 NumberFormatException の合并
        System.out.println("Bad input");
    } catch (Exception e) {
        System.out.println("Unknown error");
    }
}




/*  小结

使用try ... catch ... finally时：

	1.多个catch语句的匹配顺序非常重要，子类必须放在前面；

	2.finally语句保证了有无异常都会执行，它是可选的；

	3.一个catch语句也可以匹配多个非继承关系的异常。

*/